package yxy.game.pm2.module.therionHunting;

import org.joda.time.DateTime;
import org.redisson.api.RMap;
import yxy.apple.util.ActiveUtil;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.therionboss;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.ServerBean;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.module.BaseGameRedisLockBean;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.bean.pubsub.TherionPublisher;
import yxy.game.pm2.module.player.RankPlayerPower;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

/**
 * @author wrs
 * @name TherionModule
 * @description 神兽玩法  神兽信息模型
 * @since 2022-06-09
 */
public class TherionModule extends BaseGameRedisLockBean {

    // bean==========================================================================

    public static final int THERION_LOCAL = 1; //本服神兽争夺
    public static final int THERION_CROSS = 2; //跨服神兽猎场
    public static final int THERION_WORLD = 3; //跨服世界神兽

    public static int TSINGLUNG = 4; //青龙
    public static int WHITETIGER = 5; //白虎
    public static int ROSEFINCH = 6; //朱雀
    public static int BASALTIC = 7; //玄武

    private int gemeType; //玩法类型
    private int therionType; //神兽类型
    private int id;//神兽id
    private String name;//神兽名
    private long life; //当前血量
    private long totalLife; //总血量
    private int status;//状态 1：已死亡；2：已重生：3：复活中
    private int challengeNum; //挑战人数
    private int[] conditions; //关卡开放时间，每周的第几天
    private DateTime openTime;//开启时间
    private DateTime endTime; //结束时间
    private int rebirthtime; //复活间隔时长
    private boolean isOpen;  //是否开启
    private DateTime resurrectTime;//重生倒计时时间
    private int[] rewardtype; //击杀奖励类型
    private int[] rewardid; //击杀奖励ID
    private int[] rewardnumber;//击杀奖励数量
    private boolean isNeedSettle;//是否需要发奖励

    public int getGemeType() {
        return gemeType;
    }

    public void setGemeType(int gemeType) {
        this.gemeType = gemeType;
    }

    public int getTherionType() {
        return therionType;
    }

    public void setTherionType(int therionType) {
        this.therionType = therionType;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public int getChallengeNum() {
        return challengeNum;
    }

    public void setChallengeNum(int challengeNum) {
        this.challengeNum = challengeNum;
    }

    public int[] getConditions() {
        return conditions;
    }

    public void setConditions(int[] conditions) {
        this.conditions = conditions;
    }

    public DateTime getOpenTime() {
        return openTime;
    }

    public void setOpenTime(DateTime openTime) {
        this.openTime = openTime;
    }

    public DateTime getEndTime() {
        return endTime;
    }

    public void setEndTime(DateTime endTime) {
        this.endTime = endTime;
    }

    public int getRebirthtime() {
        return rebirthtime;
    }

    public void setRebirthtime(int rebirthtime) {
        this.rebirthtime = rebirthtime;
    }

    public boolean isOpen() {
        return isOpen;
    }

    public void setOpen(boolean open) {
        isOpen = open;
    }

    public DateTime getResurrectTime() {
        return resurrectTime;
    }

    public void setResurrectTime(DateTime resurrectTime) {
        this.resurrectTime = resurrectTime;
    }

    public long getLife() {
        return life;
    }

    public void setLife(long life) {
        this.life = life;
    }

    public int[] getRewardtype() {
        return rewardtype;
    }

    public void setRewardtype(int[] rewardtype) {
        this.rewardtype = rewardtype;
    }

    public int[] getRewardid() {
        return rewardid;
    }

    public void setRewardid(int[] rewardid) {
        this.rewardid = rewardid;
    }

    public int[] getRewardnumber() {
        return rewardnumber;
    }

    public void setRewardnumber(int[] rewardnumber) {
        this.rewardnumber = rewardnumber;
    }

    public long getTotalLife() {
        return totalLife;
    }

    public void setTotalLife(long totalLife) {
        this.totalLife = totalLife;
    }

    public boolean isNeedSettle() {
        return isNeedSettle;
    }

    public void setNeedSettle(boolean needSettle) {
        isNeedSettle = needSettle;
    }

// func===========================================================================

    //神兽名字
    public static String getName(int therionType) {

        String name = "";
        switch (therionType) {
            case 4:
                name = "青龙";
                break;
            case 5:
                name = "白虎";
                break;
            case 6:
                name = "朱雀";
                break;
            case 7:
                name = "玄武";
                break;
        }
        return name;
    }

    //玩法名字
    public static String getGameName(int gameType) {

        String name = "";
        switch (gameType) {
            case 1:
                name = "本服猎场";
                break;
            case 2:
                name = "跨服猎场";
                break;
            case 3:
                name = "世界猎场";
                break;
        }
        return name;
    }


    //初始化神兽信息
    private static void create(int type, Map<Integer, TherionModule> map) {
        Map<String, therionboss> allData = DataCenter.getAllData(therionboss.class);
        TherionHandle handle = new TherionHandle();
        for (therionboss therionboss : allData.values()) {
            TherionModule therionModule = new TherionModule();
            handle.therionModuleInit(therionModule, therionboss, type, map);
        }
    }

    //更新神兽信息
    private static void update(int gameType, String playerCode) throws RedisException {
        Map<Integer, TherionModule> therionModuleMap = touchMap(gameType, playerCode).readAllMap();
        for (Integer key : therionModuleMap.keySet()) {
            update(gameType, playerCode, key);
        }
    }

    //更新神兽信息  神兽复活
    private static void update(int gameType, String playerCode, int therionType) throws RedisException {
        TherionModule therionModule = touchMap(gameType, playerCode).readAllMap().get(therionType);
        if (therionModule.getResurrectTime() != null && therionModule.getResurrectTime().isBefore(DateTime.now())) {
            therionModule.setResurrectTime(null);
            Map<String, therionboss> allData = DataCenter.getAllData(therionboss.class);
            for (therionboss therionboss : allData.values()) {
                if (therionboss.getType() == gameType && therionboss.getName().equals(therionModule.getName())) {
                    therionModule.setLife(getLife(therionboss, playerCode));
                    therionModule.setTotalLife(getLife(therionboss, playerCode));
                    break;
                }
            }
            therionModule.setStatus(2); //已重生
            //重置开启时间、结束时间
            DateTime now = DateTime.now();
            therionModule.setOpenTime(ActiveUtil.time08_00(now));
            therionModule.setEndTime(ActiveUtil.time22_00(now));

            therionModule.set(gameType, therionType, playerCode);

            //TODO 神兽复活信息发布
            TherionPlayerModule playerModule = TherionPlayerModule.get(playerCode);
            if (playerModule != null && playerModule.getIsBooked().get(gameType).get(therionType) == 1) { //玩家已订阅
                TherionPublisher.getInstance().publish(playerCode, CCReason.神兽, gameType, therionType);
                playerModule.getIsBooked().get(gameType).put(therionType, 0); //发布完成后，取消订阅
            }

        }
    }

    //神兽复活的血量，动态获取
    public static long getLife(therionboss therionboss, String playerCode) {
        //根据战力最高的生产神兽血量
        RankPlayerPower rank = RankPlayerPower.getRank(playerCode);
        Collection<RankEntry> list = rank.range(1, 5);//取一到五名的平局值/2
        long averagePower = 0;
        for (RankEntry entry : list) {
            averagePower = averagePower + entry.getValue();
        }

        averagePower = averagePower / 5;//取平均
        long life = averagePower / 10 * 2 > therionboss.getLife() ? averagePower / 10 * 2 : therionboss.getLife();
        return life;
    }

    public static long getLife(therionboss therionboss, ArrayList<Integer> areaIds) {
        //根据战力最高的生产神兽血量
        long averagePower = 0;
        for (int i = 0; i < areaIds.size(); i++) {
            RankPlayerPower rank = RankPlayerPower.getRank(areaIds.get(i));
            Collection<RankEntry> list = rank.range(1, 5);//取一到五名的平局值/2
            for (RankEntry entry : list) {
                averagePower = averagePower + entry.getValue();
            }
        }
        averagePower = averagePower / 5 / areaIds.size();//取平均
        long life = averagePower / 10 * 2 > therionboss.getLife() ? averagePower / 10 * 2 : therionboss.getLife();
        return life;
    }


    // redis==========================================================================


    static public String key(int type, String playerCode) {
        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());
        if (type == TherionModule.THERION_LOCAL) {
            return String.format("THERION:AREA:%s:THERIONINFO", serverBean.getAreaId());
        }

        if (type == TherionModule.THERION_CROSS) {
            return String.format("THERION:AREAGROUP:%s:THERIONINFO", areaBean.getGroupId());
        }

        if (type == TherionModule.THERION_WORLD) {
            return String.format("THERION:WORLD:%s:THERIONINFO", areaBean.getGroupId());
        }
        return null;
    }


    static private RMap<Integer, TherionModule> touchMap(int type, String playerCode) throws RedisException {
        return RedisManager.client(redis()).getMap(key(type, playerCode));
    }

    public void set(int type, int therionType, String playerCode) {
        try {
            RMap<Integer, TherionModule> map = touchMap(type, playerCode);
            map.put(therionType, this);
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }

    //获取某个玩法的四个神兽
    static public Map<Integer, TherionModule> getMap(int gameType, String playerCode) {
        try {
            RMap<Integer, TherionModule> map = touchMap(gameType, playerCode);
            if (map.size() == 0) {
                create(gameType, map);
            }
            update(gameType, playerCode);
            return map.readAllMap();
        } catch (RedisException e) {
            e.printStackTrace();
        }
        return null;
    }

    //获取某个玩法的某个神兽
    static public TherionModule get(int gameType, String playerCode, int therionType) {
        try {
            RMap<Integer, TherionModule> map = touchMap(gameType, playerCode);
            if (map.size() <= 0) {
                create(gameType, map);
            }
            update(gameType, playerCode, therionType);
            return map.readAllMap().get(therionType);
        } catch (RedisException e) {
            e.printStackTrace();
        }
        return null;
    }


    //红点
    private void check() {

    }

    //存储到数据库的方法
    public static void saveToDB(String playerCode) {
    }

    //从redis移走数据的操作
    public static void removeAllFromRedis(String playerCode) {

    }

    //定时任务-----------------------------------------------------------------------------

    static public String key(int type, int areaIdOrGroupId) {
        if (type == TherionModule.THERION_LOCAL) {
            return String.format("THERION:AREA:%s:THERIONINFO", areaIdOrGroupId);
        }

        if (type == TherionModule.THERION_CROSS) {
            return String.format("THERION:AREAGROUP:%s:THERIONINFO", areaIdOrGroupId);
        }

        if (type == TherionModule.THERION_WORLD) {
            return String.format("THERION:WORLD:%s:THERIONINFO", areaIdOrGroupId);
        }
        return null;
    }

    static private RMap<Integer, TherionModule> touchMap(int type, int areaIdOrGroupId) throws RedisException {
        return RedisManager.client(redis()).getMap(key(type, areaIdOrGroupId));
    }

    public void set(int type, int therionType, int areaIdOrGroupId) {
        try {
            RMap<Integer, TherionModule> map = touchMap(type, areaIdOrGroupId);
            map.put(therionType, this);
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }

    //获取某个玩法的某个神兽
    static public TherionModule get(int gameType, int areaIdOrGroupId, int therionType) {
        try {
            RMap<Integer, TherionModule> map = touchMap(gameType, areaIdOrGroupId);
            if (map.size() <= 0) {
                create(gameType, map);
            }
            return map.readAllMap().get(therionType);
        } catch (RedisException e) {
            e.printStackTrace();
        }
        return null;
    }

    //获取某个玩法的四个神兽
    static public Map<Integer, TherionModule> getMap(int gameType, int areaIdOrGroupId) {
        try {
            RMap<Integer, TherionModule> map = touchMap(gameType, areaIdOrGroupId);
            if (map.size() <= 0) {
                create(gameType, map);
            }
            return map.readAllMap();
        } catch (RedisException e) {
            e.printStackTrace();
        }
        return null;
    }

    //更新神兽信息  神兽复活
    public static void update(int gameType, int areaIdOrGroupId, int therionType, ArrayList<Integer> areaIdList) throws RedisException {
        TherionModule therionModule = touchMap(gameType, areaIdOrGroupId).readAllMap().get(therionType);
        if (therionModule.getResurrectTime() != null && therionModule.getResurrectTime().isBefore(DateTime.now())) {
            therionModule.setResurrectTime(null);
            therionModule.setStatus(2); //已重生
            Map<String, therionboss> allData = DataCenter.getAllData(therionboss.class);
            for (therionboss therionboss : allData.values()) {
                if (therionboss.getType() == gameType && therionboss.getName().equals(therionModule.getName())) {
                    therionModule.setLife(getLife(therionboss, areaIdList));
                    therionModule.setTotalLife(getLife(therionboss, areaIdList));
                    break;
                }
            }
            therionModule.set(gameType, therionType, areaIdOrGroupId);
        }
    }

    // lock==========================================================================
    static private String lockKey(int type, String playerCode) {
        return String.format("lock:%s", key(type, playerCode));
    }

    static public boolean lockTherionModule(int type, String playerCode) throws InterruptedException {
        return tryLock(lockKey(type, playerCode));
    }

    static public void unlockTherionModule(int type, String playerCode) {
        unlock(lockKey(type, playerCode));
    }
}
